<html>
<head>
<script type="text/javascript" src="base64.js"></script>
<script type="text/javascript" src="jquery-1.4.2.min.js"></script>
<script type="text/javascript" src="chrome_ex_oauthsimple.js"></script>
<script type="text/javascript" src="chrome_ex_oauth.js"></script>
<script type="text/javascript" src="Crypto.js"></script>
<script type="text/javascript" src="SHA1.js"></script>

<script type="text/javascript" charset="utf-8">

  var OAUTH = ChromeExOAuth.initBackgroundPage({
    'request_url' : 'https://www.google.com/accounts/OAuthGetRequestToken',
    'authorize_url' : 'https://www.google.com/accounts/OAuthAuthorizeToken',
    'access_url' : 'https://www.google.com/accounts/OAuthGetAccessToken',
    'consumer_key' : 'anonymous',
    'consumer_secret' : 'anonymous',
    'scope' : 'http://picasaweb.google.com/data/',
    'app_name' : 'Clip It Good: Chrome Extension'
  });

  // Constants for various album types.
  var PICASA = 'picasa';
  var CAMLISTORE = 'camlistore';
  var ALBUM_TYPE_STRING = {
    picasa: 'Picasa Web Albums',
    camlistore: 'Camlistore'
  };

  // Preferences
  var ALBUM_CONFIG = {};  // 'type' -> ('id' -> 'name')
  var ALBUM_OPTIONS = {};  // 'type' -> ('id' -> optionsDict)

  function loadAlbumConfig() {
    var newAlbumConfig = localStorage.getItem('config:albums');
    if (newAlbumConfig) {
      ALBUM_CONFIG = $.parseJSON(newAlbumConfig);
    }

    var newAlbumOptions = localStorage.getItem('config:albumOptions');
    if (newAlbumOptions) {
      ALBUM_OPTIONS = $.parseJSON(newAlbumOptions);
    }
  }

  function saveAlbumConfig() {
    localStorage.setItem('config:albums', JSON.stringify(ALBUM_CONFIG));
    localStorage.setItem('config:albumOptions', JSON.stringify(ALBUM_OPTIONS));
  }

  // Sort albums by name.
  function getSortedAlbums(albumIdNameDict) {
    var albumIdNameArray = [];
    $.each(albumIdNameDict, function(id, name) {
      albumIdNameArray.push({'id': id, 'name': name});
    });
    albumIdNameArray.sort(function(a, b) {
      if (a['name'] < b['name']) {
        return -1;
      } else if (a['name'] > b['name']) {
        return 1;
      } else {
        return 0;
      }
    });
    return albumIdNameArray;
  }

  function setupMenus() {
    loadAlbumConfig();

    chrome.contextMenus.removeAll(function() {
      $.each(ALBUM_CONFIG, function(albumType, albumIdNameDict) {
        chrome.contextMenus.create({
          title: ALBUM_TYPE_STRING[albumType],
          contexts: ['image']
        });
        chrome.contextMenus.create({
          type: 'separator',
          contexts: ['image']
        });

        $.each(getSortedAlbums(albumIdNameDict), function(index, albumDict) {
          chrome.contextMenus.create({
            title: albumDict.name,
            contexts: ['image'],
            onclick: function(data, tab) {
              return handleMenuClick(
                  albumType, albumDict.name, albumDict.id, data, tab);
            }
          });
        });
      });
    });
  }

  // Upload actions
  var ALBUM_TYPE_UPLOAD_FUNC = {

    picasa: function(albumId, albumName, dataSrcUrl, dataBuffer, uploadDone) {
      var builder = new BlobBuilder();
      builder.append(dataBuffer);

      function complete(resp, xhr) {
        if (!(xhr.status >= 200 && xhr.status <= 299)) {
          alert('Error: Response status = ' + xhr.status +
                ', response body = "' + xhr.responseText + '"');
        } else {
          uploadDone();
        }
      }

      OAUTH.authorize(function() {
        OAUTH.sendSignedRequest(
          'http://picasaweb.google.com/data/feed/api/' +
          'user/default/albumid/' + albumId,
          complete,
          {
            method: 'POST',
            headers: {
              'Content-Type': 'image/png',
              'Slug': dataSrcUrl
            },
            parameters: {
              alt: 'json'
            },
            body: builder.getBlob('image/png')
          }
        );
      });
    },

    camlistore: function(albumId, albumName, dataSrcUrl,
                         dataBuffer, uploadDone) {
      var hash = Crypto.SHA1(new Uint8Array(dataBuffer, 0));
      var blobRef = 'sha1-' + hash;
      var options = ALBUM_OPTIONS[CAMLISTORE][albumId];

      function doUpload(uploadUrl) {
        // XXX Use real random boundary.
        var boundary = 'randomboundaryXYZ';
        var contentType = 'multipart/form-data; boundary=' + boundary;

        var header =
          '--' + boundary + '\r\n' +
          'Content-Type: application/octet-stream\r\n' +
          'Content-Disposition: form-data; name="' + blobRef +
              '"; filename="1"\r\n\r\n'
        var footer = '\r\n--' + boundary + '--\r\n';

        var builder = new BlobBuilder();
        builder.append(header);
        builder.append(dataBuffer);
        builder.append(footer);
        var payload = builder.getBlob(contentType);

        var uploadXhr = new XMLHttpRequest();
        uploadXhr.open('POST', uploadUrl, true,
                       options.username, options.password);
        uploadXhr.onreadystatechange = function() {
          if (uploadXhr.readyState == XMLHttpRequest.DONE &&
              uploadXhr.status == 200) {
            // XXX Check for bad response format (not JSON).
            var responseJson = $.parseJSON(uploadXhr.responseText)

            if (responseJson.received &&
                responseJson.received.length == 1 &&
                responseJson.received[0].blobRef == blobRef) {
              console.log('Successful upload: ' + blobRef);
              uploadDone();
              return;
            }

            alert('Camlistore upload response did not verify blob "' +
                  blobRef + '": ' + uploadXhr.responseText);
          }
          // XXX: Handle request errors
        }
        uploadXhr.setRequestHeader('Content-Type', contentType);
        uploadXhr.send(payload);
      }

      var statXhr = new XMLHttpRequest();
      statXhr.open('POST', albumId + '/camli/stat', true,
                        options.username, options.password);
      statXhr.onreadystatechange = function() {
        if (statXhr.readyState == XMLHttpRequest.DONE &&
            statXhr.status == 200) {
          // XXX Check for bad response format (not JSON).
          var responseJson = $.parseJSON(statXhr.responseText);

          if (responseJson.stat &&
              responseJson.stat.length == 1 &&
              responseJson.stat[0].blobRef == blobRef) {
            console.log('Blob already present: ' + blobRef);
            uploadDone();
            return;
          }

          var uploadUrl = responseJson.uploadUrl;
          if (!uploadUrl) {
            alert('Camlistore stat response missing "uploadUrl": ' +
                  statXhr.responseText);
            return;
          }

          doUpload(uploadUrl);
        }
        // XXX: Handle request errors
      }
      statXhr.setRequestHeader(
          'Content-Type', 'application/x-www-form-urlencoded');
      statXhr.send('camliversion=1&blob1=' + blobRef);
    }

  };

  function handleMenuClick(albumType, albumName, albumId, data, tab) {
    chrome.pageAction.setTitle({
      tabId: tab.id,
      title: 'Clip It Good: Uploading (' + data.srcUrl.substr(0, 100) + ')'
    });
    chrome.pageAction.show(tab.id);

    var img = document.createElement('img');
    img.onload = function() {
      var canvas = document.createElement('canvas');
      canvas.width = img.width;
      canvas.height = img.height;
      canvas.getContext('2d').drawImage(img, 0, 0);

      var dataUrl = canvas.toDataURL();
      var dataUrlAdjusted = dataUrl.replace('data:image/png;base64,', '');

      var arrayBuffer = Base64.decode(dataUrlAdjusted).buffer;

      function uploadDone() {
        chrome.pageAction.hide(tab.id);
      }

      var uploadFunc = ALBUM_TYPE_UPLOAD_FUNC[albumType];
      uploadFunc(albumId, albumName, data.srcUrl, arrayBuffer, uploadDone);
    }  // end onload

    img.src = data.srcUrl;
  }

  $(document).ready( function() {
    setupMenus();
  });
</script>

</head>
<body>
</body>
</html>
